package com.le.tester.utils.auth;

import com.le.tester.common.ServerResponse;
import com.le.tester.utils.IPUtil;
import com.le.tester.utils.RedisUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.reflect.SourceLocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.logging.Handler;

/**
 * createTime：2021/12/23 14:58
 * description：接口防刷实现
 */
@Aspect
@Component
public class RequestLimitAspect {

    private static final Logger LOG = LoggerFactory.getLogger(RequestLimitAspect.class);


    @Autowired
    private HttpServletRequest request;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IPUtil ipUtil;


    @Around(value = "@annotation(com.le.tester.utils.auth.RequestLimit)", argNames = "pjp")
    public Object preHandle(ProceedingJoinPoint pjp) throws Exception {

        //LOG.info("pjpSourceLocation is {}", pjp.getSourceLocation().getFileName());
        try {

            //获取到注解中的内容
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();
            RequestLimit requestLimitInfo = method.getAnnotation(RequestLimit.class);
            if (null == requestLimitInfo) {
                return ServerResponse.createByError();
            }
            //注解中的内容
            int maxCount = requestLimitInfo.maxCount();
            int second = requestLimitInfo.second();

            //设置redis中key;ip为唯一键
            String key = IPUtil.getIpAddress(request) + ":" + request.getContextPath() + ":" + request.getServletPath();

            //获取已经访问的次数
            Integer requestCount = (Integer) redisUtil.get(key);
            LOG.info("已经访问的次数:{},", requestCount);
            if (null == requestCount || -1 == requestCount) {
                redisUtil.set(key, 1, second);
                return pjp.proceed();
            }

            if (requestCount < maxCount) {
                redisUtil.incr(key, 1);
                LOG.info("正常请求");
                return pjp.proceed();
            }

            //超过了次数
            if (requestCount > maxCount) {
                LOG.info("请求过于频繁");
                return ServerResponse.createByError();
            }
            return ServerResponse.createBySuccess();
        } catch (Exception e) {
            LOG.info("接口防刷异常：{}", e.getMessage());
            return ServerResponse.createByError();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return ServerResponse.createByError();
        }
    }

}
